#include "Integer_test.hpp"


void test_integer_class() 
{
	typedef Integer<int> iint;
	
	iint p = 43;
	iint n = -p;
	iint inf = (-iint::inf()) * (-1);
	iint ind = iint::ind();
	
	assert(p == p);
	assert(p == (-n));
	
	MY_CHECK(p, is_plain());
	MY_CHECK(n, is_plain());
	MY_CHECK(n+ind, is_ind());
	MY_CHECK(n-ind, is_ind());
	MY_CHECK(ind-ind, is_ind());
	MY_CHECK(ind+ind, is_ind());
	MY_CHECK(ind/ind, is_ind());
	MY_CHECK(ind*ind, is_ind());
	MY_CHECK(ind*(-ind), is_ind());
	MY_CHECK(-ind, is_ind());
	MY_CHECK(n-n+10, is_plain());
	MY_CHECK(10+n-n, is_plain());
	MY_CHECK(10-inf, is_neginf());
	MY_CHECK(p+n, is_plain());
	MY_CHECK(p-n, is_plain());
	MY_CHECK(p+inf, is_posinf());
	MY_CHECK(p-inf, is_neginf());
	MY_CHECK(n+inf, is_posinf());
	MY_CHECK(n-inf, is_neginf());
	MY_CHECK(inf+p, is_posinf());
	MY_CHECK(inf-p, is_posinf());
	MY_CHECK(inf+n, is_posinf());
	MY_CHECK(inf-n, is_posinf());
	MY_CHECK(inf+inf, is_posinf());
	MY_CHECK(inf-inf, is_ind());
	MY_CHECK((-inf)+inf, is_ind());
	MY_CHECK(inf+(-inf), is_ind());
	MY_CHECK((-inf)-inf, is_neginf());
	MY_CHECK(inf-(-inf), is_posinf());
	MY_CHECK((-inf)-(-inf), is_ind());
	MY_CHECK(((-inf)-(-inf))+p, is_ind());
	MY_CHECK(((-inf)-(-inf))-p, is_ind());
	MY_CHECK(p+((-inf)-(-inf)), is_ind());
	MY_CHECK(p-((-inf)-(-inf)), is_ind());
	MY_CHECK(p+=1, is_plain());
	MY_CHECK(n-=1, is_plain());
	MY_CHECK(n++, is_plain());
	
	TEST_PRINT_N(p);
	TEST_PRINT_N(++p);
	TEST_PRINT_N(p++);
	TEST_PRINT_N(p);
	
	MY_CHECK(p*10, is_plain());
	MY_CHECK(p*(-10), is_plain());
	MY_CHECK(n*10, is_plain());
	MY_CHECK(n*(-10), is_plain());
	MY_CHECK(10*p, is_plain());
	MY_CHECK((-10)*p, is_plain());
	MY_CHECK(10*n, is_plain());
	MY_CHECK((-10)*n, is_plain());
	MY_CHECK(p*p, is_plain());
	MY_CHECK(n*n, is_plain());
	MY_CHECK(p*n, is_plain());
	MY_CHECK(n*p, is_plain());
	MY_CHECK(p*inf, is_posinf());
	MY_CHECK(inf*p, is_posinf());
	MY_CHECK(p*ind, is_ind());
	MY_CHECK(ind*p, is_ind());
	MY_CHECK(n*inf, is_neginf());
	MY_CHECK(inf*n, is_neginf());
	MY_CHECK(n*ind, is_ind());
	MY_CHECK(ind*n, is_ind());
	MY_CHECK(inf*inf, is_posinf());
	MY_CHECK((-inf)*(-inf), is_posinf());
	MY_CHECK(inf*(-inf), is_neginf());
	MY_CHECK((-inf)*inf, is_neginf());
	MY_CHECK(inf*ind, is_ind());
	MY_CHECK((-inf)*ind, is_ind());
	MY_CHECK(((-inf)*(-inf))+p, is_posinf());
	MY_CHECK(10*inf, is_posinf());
	MY_CHECK((-10)*(-inf), is_posinf());
	MY_CHECK((-10)*inf, is_neginf());
	MY_CHECK(inf*(-10), is_neginf());
	MY_CHECK(10*(-inf), is_neginf());
	MY_CHECK((-inf)*0, is_plain());
	MY_CHECK(inf*0, is_plain());
	MY_CHECK(0*inf, is_plain());

	MY_CHECK(sgn(n), is_plain());
	MY_CHECK(sgn(p), is_plain());
	MY_CHECK(sgn(iint(0)), is_plain());

	MY_CHECK(p/p, is_plain());
	MY_CHECK(p/n, is_plain());
	MY_CHECK(n/n, is_plain());
	MY_CHECK(n/p, is_plain());
	MY_CHECK(1/inf, is_plain());
	MY_CHECK((-1)/inf, is_plain());
	MY_CHECK(1/(-inf), is_plain());
	MY_CHECK((-1)/(-inf), is_plain());
	MY_CHECK(inf/inf, is_ind());
	MY_CHECK(iint(1)/0, is_ind());
	MY_CHECK(inf/0, is_ind());
	MY_CHECK(inf/ind, is_ind());
	
	iint ninf = -inf;
	
	TEST_PRINT_N((-inf));
	TEST_PRINT_N(23 < inf);
	TEST_PRINT_N(23 < (-inf));
	TEST_PRINT_N(23 < ninf);
	
	assert(p > n);
	assert(p >= n);
	assert(!(p < n));
	assert(!(p <= n));

	assert(n < p);
	assert(n <= p);
	assert(!(n > p));
	assert(!(n >= p));

	assert(!(2323 < -inf));
	assert(!(2323 < ninf));
	assert(!(2323 <= ninf));
	assert(p < inf);
	assert(p <= inf);
	assert(n <= inf);
	assert(0 > -inf);
	assert(!(0 < -inf));
	assert(22323 < inf);
	assert(-inf < 2323);
	assert(inf > 2323);
	assert(2323 > -inf);
	assert(!(2323 < -inf));
	assert(inf <= inf);
	assert(inf >= inf);
	assert(inf >= -inf);
	assert(-inf <= inf);
	assert(!(-inf >= inf));
	assert(!(-inf > inf));
	assert(!(inf < -inf));
	assert(!(inf < inf));
	assert(!(inf > inf));
	
	assert(!(inf > ind));
	assert(!(inf < ind));
	assert(!(-inf < ind));
	assert(!(-inf > ind));
	assert(!(ind > inf));
	assert(!(ind < inf));
	assert(!(-ind < inf));
	assert(!(-ind > inf));
	assert(!(ind > ind));
	assert(!(ind < ind));
	assert(!(-ind < ind));
	assert(!(-ind > ind));
	
	assert(!(inf >= ind));
	assert(!(inf <= ind));
	assert(!(-inf <= ind));
	assert(!(-inf >= ind));
	assert(!(ind >= inf));
	assert(!(ind <= inf));
	assert(!(-ind <= inf));
	assert(!(-ind >= inf));
	assert(!(ind >= ind));
	assert(!(ind <= ind));
	assert(!(-ind <= ind));
	assert(!(-ind >= ind));

	assert(inf == inf);
	assert(inf == (2+inf));
	assert(inf == (p+inf));
	assert(inf == (n+inf));
	assert(-inf == (n-inf));
	assert(inf != -inf);
	assert(!(inf == 2));
	assert(!(2 == inf));
	assert(p == p);
	assert(n == n);

	assert(ind != ind);
	assert(ind != -ind);
	assert(!(ind == ind));
	assert(!(p == ind));
	assert(!(inf == ind));
	assert(!(-inf == ind));
	assert(!(2 == ind));
	
	
	typedef Integer<int> iint;
	set<iint> s = {
		2, 
		4e6, 
		-4e6, 
		numeric_limits<int>::min(), 
		numeric_limits<int>::max(), 
		iint::inf(), 
		3, 
		3, 
		3, 
		iint::ind(),
		5, 
		iint::inf(), 
		-iint::inf(), 
		4, 
		-iint::inf(), 
		7
	};
	debugf(s);
		
	
	iint t = inf;
	TEST_PRINT_N((2+t*p-n*2 + 3)/2);
}
